Skip to content

ci(ff): support feature freeze automation#15433

Open
fr4nc1sc0-r4m0n wants to merge 20 commits into
elastic:mainfrom
fr4nc1sc0-r4m0n:feature/release-scripts-for-ff
Open

ci(ff): support feature freeze automation#15433
fr4nc1sc0-r4m0n wants to merge 20 commits into
elastic:mainfrom
fr4nc1sc0-r4m0n:feature/release-scripts-for-ff

Conversation

@fr4nc1sc0-r4m0n

@fr4nc1sc0-r4m0n fr4nc1sc0-r4m0n commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

This PR migrates the Elastic Agent release automation from Makefile-based scripts to a pure Go implementation using Mage, eliminating external tool dependencies for the feature-freeze workflow.

Key features

  • 8 Mage commands for release workflow automation
  • Pure Go implementation (no external CLI tools such as hub, gh, sed, yq, or Python)
  • DRY_RUN mode for safe testing without pushing changes or creating branches
  • Unit tests for the release tooling
  • Documentation in RELEASE.md and dev-tools/mage/release/README.md

Idempotency

Release workflow steps are safe to re-run without failing or creating duplicate side effects:

Step Behavior on re-run
UpdateVersion No-op when version/version.go already has the target version
UpdateDocs Skips files whose image tags already match (existing)
UpdateMergify Skips when the backport rule already exists (existing)
CreateBranch Checks out the existing branch instead of failing
CommitAll Skips commit when the worktree is clean
Push Treats already-up-to-date remote as success (existing)
CreatePR Returns the existing open PR for the same head/base

This makes mage release:runMajorMinor and mage release:runPatch resilient to CI retries and partial failures.

This branch is rebased on current main with merge conflicts resolved in go.mod, go.sum, and .mergify.yml.

Why is it important?

Supports feature-freeze automation as part of the broader release workflow effort in #12711.

Idempotent steps reduce operational risk when automation is retried after transient failures (network, auth, or partial workflow completion).

Checklist

  • I have read and understood the pull request guidelines of this project.
  • My code follows the style guidelines of this project
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • I have made corresponding change to the default configuration files
  • I have added tests that prove my fix is effective or that my feature works
  • I have added an entry in ./changelog/fragments using the changelog tool
  • I have added an integration test or an E2E test

Disruptive User Impact

No user-facing impact. This affects release automation tooling used by maintainers.

How to test this PR locally

Use a valid X.Y.Z release version (for example, the next planned minor release). Versions such as 9.5.0-test are rejected by the tooling.

export PROJECT_OWNER="your-user"
export CURRENT_RELEASE="9.6.0"
export GITHUB_TOKEN=$(gh auth token)
export DRY_RUN=true

mage release:runMajorMinor
git diff

go test ./dev-tools/mage/release/... -count=1

To verify idempotency, run the same workflow twice; the second run should complete without errors and without duplicate branches, commits, or PRs.

Related issues

Related issue: https://github.com/elastic/observability-robots/issues/3404

@fr4nc1sc0-r4m0n fr4nc1sc0-r4m0n requested a review from a team as a code owner July 9, 2026 09:35
@fr4nc1sc0-r4m0n fr4nc1sc0-r4m0n added Team:Elastic-Agent-Control-Plane Label for the Agent Control Plane team skip-changelog backport-active-all Automated backport with mergify to all the active branches labels Jul 9, 2026
@fr4nc1sc0-r4m0n fr4nc1sc0-r4m0n added Team:Elastic-Agent-Control-Plane Label for the Agent Control Plane team skip-changelog backport-active-all Automated backport with mergify to all the active branches labels Jul 9, 2026
@fr4nc1sc0-r4m0n fr4nc1sc0-r4m0n self-assigned this Jul 9, 2026
@infra-vault-gh-plugin-prod

Copy link
Copy Markdown

Pinging @elastic/elastic-agent-control-plane (Team:Elastic-Agent-Control-Plane)

1 similar comment
@infra-vault-gh-plugin-prod

Copy link
Copy Markdown

Pinging @elastic/elastic-agent-control-plane (Team:Elastic-Agent-Control-Plane)

Validate and allowlist repository paths before writing release files,
and update tests to use supported relative manifest paths.
Allow re-running release workflows without duplicate branches,
empty commits, duplicate PRs, or false version-update errors.
}

// Pattern: docker.elastic.co/elastic-agent/elastic-agent:X.Y.Z
re := regexp.MustCompile(`(docker\.elastic\.co/elastic-agent/elastic-agent:)[0-9]+\.[0-9]+\.[0-9]+`)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way we can generalize? or at least surface the pattern to the magefile?

return fmt.Errorf("failed to checkout existing branch: %w", err)
}

fmt.Printf("✓ Checked out existing branch: %s\n", branchName)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want this? If someone creates a branch beforehand, we will checkout that and continue working, which could inject unwanted code.

Comment thread magefile.go
return err
}

dryRun := os.Getenv("DRY_RUN") == "true"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
dryRun := os.Getenv("DRY_RUN") == "true"
var dryRun bool
if v, err := strconv.ParseBool(os.Getenv("DRY_RUN")); err == nil {
dryRun = v
}

maybe? or at least

Suggested change
dryRun := os.Getenv("DRY_RUN") == "true"
dryRun := strings.ToLower(os.Getenv("DRY_RUN")) == "true"

Replace invalid 9.5.0-test examples with 9.6.0 and document the
required version format for local release workflow testing.
Use go-git CheckoutOptions.Keep so major/minor release workflow can
prepare version files before checking out the release branch.
Replace go-git AddWithOptions(All: true) with per-path staging from
worktree status so CommitAll includes every changed path (including
submodule gitlinks like beats) without reading submodule directories.
Match the Beats release automation by requiring GITHUB_TOKEN for push
operations and authenticating via HTTP basic auth with an explicit
branch refspec.
@swiatekm

Copy link
Copy Markdown
Member

buildkite test this

@github-actions

This comment has been minimized.

@github-actions

Copy link
Copy Markdown
Contributor

TL;DR

The Windows unit-test failures are a real regression in the new release tooling, independent of the Beats submodule mismatch already reported above. validateRepoRelativePath cleans paths with the host OS separator, but writeRepoFile allowlists only /-separated strings; on Windows version/version.go becomes version\version.go and is rejected as unsupported.

Remediation

  • Make the allowlist comparison platform-independent, for example by comparing filepath.ToSlash(safePath) with slash-separated constants, or by constructing the allowlist entries with filepath.Join.
  • Add/run the release package tests on Windows (especially TestUpdateVersion, TestUpdateDocs, TestUpdateVersionInFile, and TestPrepareMajorMinorRelease) and rerun the Windows matrix.
Investigation details

Root Cause

In dev-tools/mage/release/release.go:18-31, validateRepoRelativePath returns filepath.Clean(path). In writeRepoFile (release.go:33-47), the subsequent switch compares that cleaned value to literals such as version/version.go and deploy/kubernetes/elastic-agent-managed-kubernetes.yaml. On Windows, filepath.Clean produces version\version.go, so every write through this allowlist fails. The same path is passed by UpdateVersion and updateVersionInFile, causing the eight release-test failures.

The tests change into a temporary directory before invoking the functions (dev-tools/mage/release/release_test.go:18-49, 99-149, and 167-223), so the failure is in the production path validation rather than test fixture setup.

Evidence

  • Build: https://buildkite.com/elastic/elastic-agent/builds/42775
  • Windows logs: TestUpdateVersion fails with failed to write version\version.go: unsupported file path: version\version.go (lines 103-126); TestUpdateDocs and TestUpdateVersionInFile fail with the same separator mismatch (lines 115-125).
  • The identical eight release failures occur on Windows 11, Windows 11 arm64, and fips140=only Windows 11 arm64.
  • The ESS cleanup failure reports No artifacts found for downloading after the FIPS setup/package path failed; it is a downstream cleanup symptom, not an additional root cause.

Verification

Not reproduced locally because this checkout does not contain the PR branch’s new dev-tools/mage/release package and the failing Buildkite jobs are Windows-specific.


What is this? | From workflow: PR Buildkite Detective

Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport-active-all Automated backport with mergify to all the active branches skip-changelog skip-ci Team:Elastic-Agent-Control-Plane Label for the Agent Control Plane team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants